package frame.service.standard.impl;

import frame.service.context.ServiceContext;
import frame.service.standard.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Set;

public abstract class AbstractServiceExecutor implements ServiceExec {
    private Logger logger = LoggerFactory.getLogger(AbstractServiceExecutor.class);

    @Autowired(required = false)
    protected List<MiayFilter> filters;

    @Override
    public void serviceInvoke(ServiceContext context) {
        //服务统一过滤器，通过checkSuit校验是否需通过过滤器，doPass完成过滤
        if(filters!=null && filters.size()!=0){
            for(MiayFilter filter: filters){
                if(filter.checkSuit(context)){
                    filter.doPass(context);
                }
            }
        }

        try {
            ServiceInfo serviceInfo = getServiceInfo(context);
            if(serviceInfo==null){
                logger.error("920001");
                throw new MiayRuntimeException("920001");
            }
            String httpMethod = context.getReqContentString(Constants.REQUEST_HTTP_METHOD);
            if(!serviceInfo.checkSupportHttpMethod(httpMethod)){
                logger.error("910001");
                throw new MiayRuntimeException("910001", new Object[]{httpMethod});
            }
            innerExec(serviceInfo, context);
        }catch (Exception e){
            if(e instanceof InvocationTargetException){
                if(((InvocationTargetException) e).getTargetException() instanceof MiayRuntimeException){
                    throw (MiayRuntimeException)((InvocationTargetException) e).getTargetException();
                }
                throw new MiayRuntimeException(((InvocationTargetException) e).getTargetException());
            }else{
                throw new MiayRuntimeException(e);
            }
        }
    }

    public abstract void innerExec(ServiceInfo serviceInfo, ServiceContext serviceContext) throws Exception;
    public abstract ServiceInfo getServiceInfo(ServiceContext context);

    public static class ServiceInfo{
        private String serviceId;
        private Object object;
        private Map<String, Method> supportAction;
        private Set<String> supportHttpMethod;
        private List<ServiceCheck> checks;

        public void setObject(Object object) {
            this.object = object;
        }

        public Object getObject() {
            return object;
        }

        public void setServiceId(String serviceId) {
            this.serviceId = serviceId;
        }

        public String getServiceId() {
            return serviceId;
        }

        public void setSupportAction(Map<String, Method> supportAction) {
            this.supportAction = supportAction;
        }

        public Map<String, Method> getSupportAction() {
            return supportAction;
        }

        public void setSupportHttpMethod(Set<String> supportHttpMethod) {
            this.supportHttpMethod = supportHttpMethod;
        }
        public boolean checkSupportHttpMethod(String httpMethod){
            return supportHttpMethod.contains(httpMethod);
        }

        public Set<String> getSupportHttpMethod() {
            return supportHttpMethod;
        }

        public List<ServiceCheck> getChecks() {
            return checks;
        }

        public void setChecks(List<ServiceCheck> checks) {
            this.checks = checks;
        }
    }
}
